/**
 * 1.5.472 (2009/08/14)
 *
 * Copyright © 2009 Paul Chapman
 *
 * This file is part of KAE.
 *
 * KAE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * KAE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with KAE.  If not, see <http://www.gnu.org/licenses/>.
 */
"use strict";
/*global Sizzle, NodeList */
var KAE = KAE || {};
(function () {
    /**
     * Rather than create `F` every time KAE.query is run, we encapsulate
     * it in an anonymous function. This is much faster.
     */
    function F(select, context) {
        // This handles the case where you pass in an HTMLElement or NodeList.
        if (typeof select === "string") {
            // Set properties that a user or plugin may find useful.
            this.selector = select;
            this.context = context;
            if (context) {
                // Returns only the elements that are children of `context`.
                select = this.slice.call(this.childOf(context));
            } else {
                try {
                    // This turns the NodeList into a genuine array.
                    select = this.slice.call(document.querySelectorAll(select));
                } catch (e) {
                    // Fall back to Sizzle if we don't have querySelectorAll.
                    select = Sizzle(select);
                }
            }
        } else if (select instanceof Element) {
            // We wrap the HTMLElement in an array, so `apply` will work.
            select = [select];
        } else if (select instanceof NodeList) {
            // This turns the NodeList into a genuine array.
            select = this.slice.call(select);
        }
        // Converts KAE.query into a fake array (like NodeList).
        this.push.apply(this, select);
    }

    /**
     * A shorthand for querySelectorAll.
     * Also allows for extending via plugins, a la jQuery.
     */
    KAE.query = function (select, context) {
        return new F(select, context);
    };

    // KAE.query now has access to the Array methods, like forEach.
    // Also allows for adding plugins under the alias `KAE.query.prototype`.
    F.prototype = KAE.query.prototype = [];

    // Array.prototype.toString is *not* generic, which is ludicrous.
    // So, we assign it to the generic Object.prototype.toString, so we don't
    // get any crazy errors.
    KAE.query.prototype.toString = Object.prototype.toString;
}());

/**
 * Returns the elements that are children of the supplied element.
 */
KAE.query.prototype.childOf = function (elem) {
    var output, old = elem.getAttribute("data-context");

    // Set the `data-context` of the element, to create a fake context.
    elem.setAttribute("data-context", "KAE.query");

    // Return the elements that are descendants of the context.
    output = KAE.query("[data-context='KAE.query'] " + this.selector);

    // Changes the `data-context` back to what it was before.
    ((old === null) ?
        elem.removeAttribute("data-context") :
        elem.setAttribute("data-context", old));

    // This ensures that the selector and context are correct.
    output.selector = this.selector;
    output.context = elem;

    // childOf is non-destructive: it doesn't modify the original query.
    return output;
};
